package reactor.spring.context.config;
import java.util.Map;
import java.util.function.Supplier;
import org.reactivestreams.Processor;
import reactor.core.publisher.EmitterProcessor;
import reactor.core.publisher.FluxProcessor;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
import reactor.core.scheduler.TimedScheduler;
import reactor.util.Loggers;
import reactor.spring.factory.CreateOrReuseFactoryBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.StringUtils;
/**
* {@link ImportBeanDefinitionRegistrar} implementation that configures necessary Reactor components.
*
* @author Jon Brisbin
* @author Stephane Maldini
*/
public class ReactorBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
private static final String DEFAULT_TIMER_SUPPLIER_NAME = "reactorTimer";
private static final String DEFAULT_SCHEDULER_GROUP_NAME = "reactorGroupedProcessors";
private static final Supplier<Supplier<Processor>> DEFAULT_SCHEDULER_GROUP = () -> {
final Scheduler group =
Schedulers.newParallel(DEFAULT_SCHEDULER_GROUP_NAME + "-spring");
return (Supplier<Processor>) () -> {
FluxProcessor emitter = EmitterProcessor.create();
return FluxProcessor.wrap(emitter, emitter.publishOn(group));
};
};
private static final Supplier<Supplier<TimedScheduler>> DEFAULT_TIMER_SUPPLIER = () -> {
final TimedScheduler timer = Schedulers.newTimer("spring-timer");
return () -> timer;
};
protected <T> void registerReactorBean(BeanDefinitionRegistry registry,
String attrValue,
String name, Class<T> tClass, Supplier<Supplier<T>> supplier) {
// Create a root Enivronment
if (!registry.containsBeanDefinition(name)) {
BeanDefinitionBuilder envBeanDef = BeanDefinitionBuilder.rootBeanDefinition(CreateOrReuseFactoryBean
.class);
envBeanDef.addConstructorArgValue(name);
envBeanDef.addConstructorArgValue(tClass);
if (StringUtils.hasText(attrValue)) {
envBeanDef.addConstructorArgReference(attrValue);
} else {
envBeanDef.addConstructorArgValue(supplier.get());
}
registry.registerBeanDefinition(name, envBeanDef.getBeanDefinition());
}
}
@Override
public void registerBeanDefinitions(AnnotationMetadata meta, BeanDefinitionRegistry registry) {
Map<String, Object> attrs = meta.getAnnotationAttributes(EnableReactor.class.getName());
registerReactorBean(registry,
(String) attrs.get("timerSupplier"),
DEFAULT_TIMER_SUPPLIER_NAME,
TimedScheduler.class,
DEFAULT_TIMER_SUPPLIER
);
registerReactorBean(registry,
(String) attrs.get("processorSupplier"),
DEFAULT_SCHEDULER_GROUP_NAME,
Processor.class,
DEFAULT_SCHEDULER_GROUP
);
// Create a ConsumerBeanAutoConfiguration
if (!registry.containsBeanDefinition(ConsumerBeanAutoConfiguration.class.getName())) {
BeanDefinitionBuilder autoConfigDef = BeanDefinitionBuilder.rootBeanDefinition
(ConsumerBeanAutoConfiguration.class);
registry.registerBeanDefinition(ConsumerBeanAutoConfiguration.class.getName(), autoConfigDef
.getBeanDefinition());
}
}
}